import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt


class HousePricePredictor:
    def __init__(self):
        self.model = LinearRegression()
        self.scaler = StandardScaler()
    
    def load_and_prepare_data(self):
        data= pd.DataFrame({
            'size': [85,120,150,100,90,160,140,110,130,170],
            'rooms': [2,3,4,3,2,4,4,3,3,5],
            'location_score': [8,7,9,6,5,8,7,6,8,9],
            'price': [350000,520000,680000,420000,390000,
                        700000,650000,480000,580000,780000]
        })

        #分离特征和目标
        X = data[['size', 'rooms', 'location_score']]
        y = data['price']

        # 数据分割
        X_train, X_test, y_train, y_test = train_test_split(
            X, y, test_size=0.2, random_state=42
        )

        # 特征标准化
        X_train_scaled = self.scaler.fit_transform(X_train)
        X_test_scaled = self.scaler.transform(X_test)

        return X_train_scaled, X_test_scaled, y_train, y_test, X_train.columns
    
    def train_model(self, X_train, y_train):
        self.model.fit(X_train, y_train)

    def evaluate_model(self, X_test, y_test, feature_names):
        # 预测
        y_pred = self.model.predict(X_test)

        # 计算评估指标
        mse = mean_squared_error(y_test, y_pred)
        r2 = r2_score(y_test, y_pred)

        print("\n模型评估结果:")
        print(f"均方误差 (MSE):{mse:.2f}")
        print(f"R² 分数:{r2:.2f}")

        print("\n特征重要性:")

        for name, coef in zip(feature_names, self.model.coef_):
            print(f"{name}:{coef:.2f}")
        
        return y_pred
    
    def visualize_results(self, y_test, y_pred):
        plt.rcParams['font.family'] = ['Microsoft YaHei']
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
        plt.figure(figsize=(10,6))
        plt.scatter(y_test, y_pred)
        plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()],'r--', lw=2)
        plt.xlabel('实际价格')
        plt.ylabel('预测价格')
        plt.title('预测价格 vs 实际价格')
        plt.tight_layout()

        return plt
    
    def predict_price(self, features):
        features_scaled = self.scaler.transform(features)
        predicted_price = self.model.predict(features_scaled)
        return predicted_price[0]
    
def main():
    # 创建预测器实例
    predictor = HousePricePredictor()
    
    # 加载和准备数据
    X_train, X_test, y_train, y_test, feature_names = predictor.load_and_prepare_data()

    # 训练模型
    predictor.train_model(X_train, y_train)

    # 评估模型
    y_pred = predictor.evaluate_model(X_test, y_test, feature_names)

    # 可视化结果
    plt = predictor.visualize_results(y_test, y_pred)
    plt.show()

    # 预测新房价
    new_house = np.array([[130,3,7]])  # 面积、房间数、地段评分
    predicted_price = predictor.predict_price(new_house)
    print(f"\n新房预测价格: ${predicted_price:,.2f}")

if __name__ =="__main__":
    main()